// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import GameConfig from "../game/GameConfig";
import UnitList from "../game/UnitList";
import EventManager from "../manager/EventManager";
import UnitManager from "../manager/UnitManager";
import SkinCreate from "../utils/SkinCreate";
import MapUtil from "./MapUtil";

const { ccclass, property } = cc._decorator;

@ccclass
export default class MapLogic extends cc.Component {

    @property(cc.Node)
    m_camera: cc.Node = null;
    @property(cc.TiledMap)
    m_tiledMap: cc.TiledMap = null
    @property(cc.Node)
    m_touchNode: cc.Node = null;
    //@property(cc.Node)
    heroNode: cc.Node = null; // heroNode
    @property(cc.Node)
    unitList: cc.Node = null; // unitList
    @property(cc.Node)
    m_showLabel: cc.Node = null;
    @property(cc.Node)
    m_rangeNode: cc.Node = null;


    m_moveRangeNode: cc.Node = null;
    protected _tiledMap: cc.TiledMap = null;
    protected _mapCamera: cc.Camera = null;
    protected _isTouch: boolean = false;
    protected _isMove: boolean = false;
    //地图相机移动边界
    protected _maxMapX: number = 1;
    protected _maxMapY: number = 1;

    isUnitMove: boolean = false;

    private path: cc.Vec2[] = []; // A* 寻路算法返回的路径
    private currentTargetIndex: number = 0; // 当前路径目标的索引

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        console.log("MapLogic onLoad");
        this._mapCamera = this.m_camera.getComponent(cc.Camera);
        MapUtil.initMapConfig(this.m_tiledMap);
        this.setTiledMap(this.m_tiledMap);
        this.unitList.getComponent(UnitList).setUnit()
        //this.showLabel();
        EventManager.Inst.on("UnitNode-ShowMoveRange",this,()=>{
            //console.log(this.heroNode)
            this.heroNode = this.unitList.getComponent(UnitList).curr_UnitNode;
            let t_v2 = MapUtil.mapPixelToCellPoint(cc.v2(this.heroNode.position.x,this.heroNode.position.y));
            this.showMoveRange(t_v2);
        })

    }


    showLabel() {
        var mapSize = MapUtil.mapSize;
        for (let y = 0; y < mapSize.height; y++) {
            for (let x = 0; x < mapSize.width; x++) {
                var t_label = new cc.Node();
                t_label.parent = this.m_showLabel;
                t_label.addComponent(cc.Label)
                t_label.getComponent(cc.Label).string = x + "," + y;
                let v2 = MapUtil.mapCellToPixelPoint(cc.v2(x, y))
                t_label.setPosition(v2.x, v2.y);
            }
        }
    }

    public setTiledMap(tiledMap: cc.TiledMap) {
        //
        this._tiledMap = tiledMap;
        this._tiledMap.enableCulling(true)
        var uit = this._tiledMap.node;
        this._maxMapX = (uit.width - cc.view.getVisibleSize().width) * 0.5;
        this._maxMapY = (uit.height - cc.view.getVisibleSize().height) * 0.5;
        //this._tiledMap.node.on(Node.EventType.MOUSE_WHEEL, this.onMouseWheel, this);
        this._tiledMap.node.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan, this);
        this._tiledMap.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this._tiledMap.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this._tiledMap.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    }

    protected onTouchBegan(event: cc.Event.EventTouch): void {
        this._isTouch = true;
        this._isMove = false;
    }
    protected onTouchCancel(event: cc.Event.EventTouch): void {
        this._isTouch = false;
        this._isMove = false;
    }
    protected onTouchEnd(event: cc.Event.EventTouch): void {
        this._isTouch = false;
        if (this._isMove == false) {
            let touchLocation: cc.Vec2 = event.touch.getLocation();
            let touchLocation1 = this.viewPointToWorldPoint(touchLocation);
            let mapPoint: cc.Vec2 = MapUtil.worldPixelToMapCellPoint(touchLocation1);
            let clickCenterPoint: cc.Vec2 = MapUtil.mapCellToPixelPoint(mapPoint);
            //派发事件
            //console.log("onTouchEnd:", touchLocation1, clickCenterPoint);
            if (!this.m_touchNode.active) {
                this.m_touchNode.active = true;
            }
            this.m_touchNode.setPosition(clickCenterPoint.x, clickCenterPoint.y);
            //EventMgr.emit(LogicEvent.touchMap, mapPoint, clickCenterPoint);
            
            if (this.heroNode && !GameConfig.isUnitMove) {
                // 调用 A* 寻路算法
                this.path = MapUtil.aStarSearch(cc.v2(this.heroNode.x, this.heroNode.y), clickCenterPoint);

                // 如果找到路径，开始移动 heroNode
                if (this.path.length > 0) {
                    this.currentTargetIndex = this.path.length - 1;
                    this.moveToTarget(this.path);
                    if (this.m_moveRangeNode) {
                        this.m_moveRangeNode.destroy();
                    }
                    //console.log("path:", this.path);
                }
            }

        }
        this._isMove = false;
        // this._isTouch = false;
        // this._isMove = false;
    }
    protected onTouchMove(event: cc.Event.EventTouch): void {
        if (this._isTouch) {
            let delta: cc.Vec2 = event.getDelta();
            if (delta.x != 0 || delta.y != 0) {
                this._isMove = true;
                let pixelPoint: cc.Vec2 = new cc.Vec2(0, 0);
                pixelPoint.x = this._mapCamera.node.position.x - delta.x;
                pixelPoint.y = this._mapCamera.node.position.y - delta.y;
                pixelPoint.x = Math.min(this._maxMapX, Math.max(-this._maxMapX, pixelPoint.x));
                pixelPoint.y = Math.min(this._maxMapY, Math.max(-this._maxMapY, pixelPoint.y));
                this._mapCamera.node.setPosition(new cc.Vec3(pixelPoint.x, pixelPoint.y, this._mapCamera.node.position.z));
                //this.setCenterMapCellPoint(MapUtil.mapPixelToCellPoint(pixelPoint), pixelPoint);
                //this.updateCulling();
            }
        }
    }

    // 移动 heroNode 到目标位置
    moveToTarget(path) {
        if (!this.heroNode) return;
        GameConfig.isUnitMove = true;
        this.heroNode.stopAllActions();

        let moveActions = [];
        let lastPosition = cc.v3(this.heroNode.position); // 保存初始位置
        let lastDirection = "";

        for (let i = 0; i < path.length; i++) {
            const targetWorld = MapUtil.mapCellToPixelPoint(path[i]);
            const distance = lastPosition.sub(cc.v3(targetWorld.x, targetWorld.y)).mag();
            const duration = distance / 350;
            const direction = this.GetUnityDirection(lastPosition, targetWorld);

            if (direction !== lastDirection) {
                lastDirection = direction;
                const animAction = cc.callFunc(() => {
                    //this.heroNode.getChildByName("animNode").getComponent(cc.Animation).play("kuwei-move-" + direction);
                    this.heroNode.getChildByName("animNode").getComponent(SkinCreate).playAnim("move", direction)
                    //console.log("kuwei-move-" + direction);
                }, this);
                moveActions.push(animAction);
            }

            const moveAction = cc.moveTo(duration, targetWorld);
            moveActions.push(moveAction);

            // 更新 lastPosition 为当前目标点位置，以便下一个循环使用
            lastPosition = cc.v3(targetWorld.x, targetWorld.y);
        }

        const finished = cc.callFunc(() => {
            console.log("到达目的地");
            if (lastDirection == "") {
                lastDirection = "down"
            }
            this.heroNode.getChildByName("animNode").getComponent(SkinCreate).playAnim("wait", lastDirection)
            GameConfig.isUnitMove = false;
            //this.heroNode = null;
        }, this);
        moveActions.push(finished);

        const moveSequence = cc.sequence(moveActions);
        this.heroNode.runAction(moveSequence);
    }


    //界面坐标转世界坐标
    protected viewPointToWorldPoint(point: cc.Vec2): cc.Vec2 {
        // console.log("viewPointToWorldPoint in", point.x, point.y);

        let canvasNode: cc.Node = this.node.parent;
        let cuit = canvasNode;
        let uit = this._tiledMap.node;


        let cameraWorldX: number = uit.width * uit.anchorX - cc.view.getVisibleSize().width * cuit.anchorX + this._mapCamera.node.position.x;
        let cameraWorldY: number = uit.height * uit.anchorY - cc.view.getVisibleSize().height * cuit.anchorY + this._mapCamera.node.position.y;

        return new cc.Vec2(point.x + cameraWorldX, point.y + cameraWorldY);
    }
    radiansToDegrees(radians) {
        return radians * (180 / Math.PI);
    }
    // 计算方向的函数
    GetUnityDirection(p1, p2): string {
        let angle = (Math.atan2(p2.y - p1.y, p2.x - p1.x) * (180 / Math.PI));
        angle = (angle + 360) % 360;
        // 2 up,6 down, 4 left,0 right,   1 up-right, 7 down-right, 3 down-left, 5 up-left
        //let dirTag = [];
        let dirTag = ["right", "rightup", "up", "leftup", "left", "leftdown", "down", "rightdown"];
        let temp = 360 / 8; // Divide into 8 directions
        let dir = 0;
        for (let i = 0; i < 8; i++) {
            if (angle >= i * temp - temp / 2 && angle < i * temp + temp / 2) {
                dir = i;
                break;
            }
        }
        //console.log("angle: ", angle, "dir: ", dir, "dir: ", dirTag[dir]);
        return dirTag[dir];
    }

    // 显示移动范围
    private showMoveRange(center: cc.Vec2) {
        // 隐藏之前的移动范围节点
        if (this.m_moveRangeNode) {
            this.m_moveRangeNode.destroy();
        }

        // 创建移动范围节点
        this.m_moveRangeNode = new cc.Node();
        this.m_moveRangeNode.parent = this._tiledMap.node;

        // 获取可移动范围
        const moveRange = MapUtil.getMoveRange(center, 4);

        // 创建范围节点
        for (const point of moveRange) {
            const rangeNode = cc.instantiate(this.m_rangeNode);
            rangeNode.active = true;
            // 设置范围节点位置
            const worldPoint = MapUtil.mapCellToPixelPoint(point);
            rangeNode.setPosition(worldPoint);

            // 将范围节点添加到父节点
            rangeNode.parent = this.m_moveRangeNode;
        }
    }
    start() {

    }

    // update (dt) {}
}
